﻿using System.Collections.Generic;
using System.IO;
using UpdaterForm.Utils;

namespace UpdaterForm.CustomTreeView
{
    public class UpdateTreeView : Observable
    {
        #region Data

        private bool? _isChecked = false;
        private UpdateTreeView _parent;

        #endregion // Data

        #region Properties 

        public List<UpdateTreeView> Children { get; private set; }
        public bool IsInitiallySelected { get; private set; }

        public string Name { get; private set; }
        public string FullName { get; private set; }

        #region IsChecked

        /// <summary>
        ///     Gets/sets the state of the associated UI toggle (ex. CheckBox).
        ///     The return value is calculated based on the check state of all
        ///     child FooViewModels.  Setting this property to true or false
        ///     will set all children to the same check state, and setting it
        ///     to any value will cause the parent to verify its check state.
        /// </summary>
        public bool? IsChecked
        {
            get { return _isChecked; }
            set { SetIsChecked(value, true, true); }
        }

        private void SetIsChecked(bool? value, bool updateChildren, bool updateParent)
        {
            if (value == _isChecked)
                return;

            _isChecked = value;

            if (updateChildren && _isChecked.HasValue)
                Children.ForEach(c => c.SetIsChecked(_isChecked, true, false));

            if (updateParent && _parent != null)
                _parent.VerifyCheckState();

            OnPropertyChanged("IsChecked");
        }

        private void VerifyCheckState()
        {
            bool? state = null;
            for (int i = 0; i < Children.Count; ++i)
            {
                bool? current = Children[i].IsChecked;
                if (i == 0)
                {
                    state = current;
                }
                else if (state != current)
                {
                    state = null;
                    break;
                }
            }
            SetIsChecked(state, false, true);
        }

        #endregion // IsChecked

        #endregion

        #region Create

        private UpdateTreeView(DirectoryInfo dir)
        {
            //TODO: Mozet sohranit dir kak property ? Eli nado bolwe info
            Name = dir.Name;
            Children = new List<UpdateTreeView>();
            //TODO: Mozet sdelat otdelnie classi dla failov i directori
            //TODO: LazyLoading mozet prigoditsa
            DirectoryInfo[] subDirs = dir.GetDirectories();
            foreach (DirectoryInfo subDir in subDirs)
            {
                Children.Add(new UpdateTreeView(subDir));
            }

            FileInfo[] files = FileUtil.ListFiles(dir);
            foreach (FileInfo file in files)
                Children.Add(new UpdateTreeView(file.Name));
        }


        private UpdateTreeView(DirectoryInfo dir, UpdateLog log)
        {
            Name = dir.Name;
            Children = new List<UpdateTreeView>();
            DirectoryInfo[] subDirs = dir.GetDirectories();
            foreach (DirectoryInfo subDir in subDirs)
            {
                Children.Add(new UpdateTreeView(subDir));
            }

            FileInfo[] files = FileUtil.ListFiles(dir);
            foreach (FileInfo file in files)
            {
                var node = new UpdateTreeView(file.Name)
                {
                    IsChecked = log.TransferedFiles.Contains(file.FullName)
                };
                Children.Add(node);
            }
        }

        private UpdateTreeView(string name)
        {
            Name = name;
            Children = new List<UpdateTreeView>();
        }

        public static List<UpdateTreeView> LoadFromDirInfo(DirectoryInfo info)
        {
            var tree = new UpdateTreeView(info);
            tree.Initialize();
            tree.IsInitiallySelected = true;
            tree.IsChecked = true;
            return tree.Children;
        }

        //TODO: navernoe mozno objedenit ispolzuemie polja DirInfo i Log v Update
        public static List<UpdateTreeView> LoadFromDirInfo(DirectoryInfo info, UpdateLog log)
        {
            var tree = new UpdateTreeView(info, log);
            tree.Initialize();
            return tree.Children;
        }

        private void Initialize()
        {
            foreach (UpdateTreeView child in Children)
            {
                child._parent = this;
                child.Initialize();
            }
        }

        #endregion // Create
    }
}